1 module hip.gui.screen;
2 public import hip.gui.widget;
3 import hip.api.input.button;
4 import std.internal.digest.sha_SSSE3;
5 import hip.gui.group;
6 
7 /** 
8  * Screen is where all widgets should be contained.
9  * This way, the event methods are forwarded correctly, there can exist a drag and drop.
10  * Render order by stack is also possible
11  */
12 class Screen : Group
13 {
14     protected Widget focusedWidget;
15     protected Widget draggedWidget;
16     private Widget widgetHolded;
17     private Widget widgetMouseEntered;
18 
19 
20     this(){setupEvents();}
21 
22     private const(HipButton)* mouseDownEv, mouseUpEv;
23     private const(ScrollListener)* scrollEv;
24     private const(TouchMoveListener)* moveEv;
25 
26 
27 
28     final void setupEvents()
29     {
30         import hip.api.input.core:HipInput, HipInputListener, HipMouseButton;
31         mouseDownEv = HipInputListener.addTouchListener(HipMouseButton.left, 
32         (const AHipButtonMetadata meta)
33         {
34             handleMouseDown();
35         });
36 
37         mouseUpEv = HipInputListener.addTouchListener(HipMouseButton.left,
38         (const(AHipButtonMetadata) meta)
39         {
40             stopDragging();
41             handleMouseUp();
42         }, HipButtonType.up);
43 
44         moveEv = HipInputListener.addTouchMoveListener((int x, int y)
45         {
46             handleMouseEnter(x, y);
47             startDragging(x, y);
48         });
49         
50         scrollEv = HipInputListener.addScrollListener((float[3] scroll)
51         {
52             handleScroll(scroll);
53         });
54     }
55     
56 
57     int findWidget(Widget w)
58     {
59         for(int i = 0; i < children.length; i++) 
60             if(children[i] is w) return i;
61         return -1;
62     }
63 
64     private void handleMouseDown()
65     {
66         import hip.api;
67         Widget w = findWidgetAt(HipInput.getWorldTouchPosition());
68         widgetHolded = w;
69         setFocusOn(w);
70         if(w !is null) w.onMouseDown();
71     }
72     private void handleMouseUp()
73     {
74         import hip.api;
75         if(widgetHolded !is null)
76         {
77             widgetHolded.onMouseUp();
78             if(findWidgetAt(HipInput.getWorldTouchPosition()) is widgetHolded)
79                 widgetHolded.onMouseClick();
80         }
81         widgetHolded = null;
82     }
83     private void handleScroll(float[3] scroll)
84     {
85         import hip.api;
86         Widget w = findWidgetAt(HipInput.getWorldTouchPosition());
87         setFocusOn(w);
88         if(w !is null)
89         {
90             import hip.gui.scroll_area;
91             IRawScrollable scrollable = cast(IRawScrollable)w;
92             if(scrollable !is null) scrollable.onRawScroll(scroll);
93         }
94     }
95 
96     private void handleMouseEnter(int x, int y)
97     {
98         Widget mEnterWidget = findWidgetAt(x, y);
99         if(widgetMouseEntered !is mEnterWidget)
100         {
101             if(widgetMouseEntered)
102                 widgetMouseEntered.onMouseExit();
103             if(mEnterWidget)
104                 mEnterWidget.onMouseEnter();
105         }
106         widgetMouseEntered = mEnterWidget;
107     }
108     private void startDragging(int x, int y)
109     {
110         if(widgetHolded && !draggedWidget)
111         {
112             setDragging(widgetHolded, x , y);
113         }
114         if(draggedWidget !is null)
115             draggedWidget.onDragged(x, y);
116     }
117 
118     private void pushToTop(Widget w)
119     {
120         int pos = findWidget(w);
121         if(pos == children.length-1) return;
122         else if(pos != -1)
123         {
124             import hip.api;
125             import hip.util.algorithm;
126             children[pos+1..$].copyInto(children[pos..$-1]);
127             children[$-1] = w;
128         }
129     }
130 
131     void setFocusOn(Widget w)
132     {
133         if(focusedWidget is w) return;
134         if(focusedWidget !is null)
135             focusedWidget.onFocusExit();
136         focusedWidget = w;
137         if(w !is null)
138         {
139             pushToTop(w);
140             w.onFocusEnter();
141         }
142     }
143 
144     void setDragging(Widget w, int x, int y)
145     {
146         if(w !is null && w.isDraggable)
147         {
148             w.onDragStart(x, y);
149             draggedWidget = w;
150         }
151     }
152 
153     void stopDragging()
154     {
155         if(draggedWidget !is null)
156         {
157             draggedWidget.onDragEnd();
158             draggedWidget = null;
159         }
160     }
161 
162 }